home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / tutorials / geometer / prims.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  19.5 KB  |  802 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. #include "parse.h"
  19. #include <gl.h>
  20. #include <math.h>
  21. #include <malloc.h>
  22.  
  23. extern float fxmin, fxmax, fymin, fymax;
  24.  
  25. short defaultwidth = 1;
  26. long showinvisible = 0;
  27. long showinfo = 1;
  28. long inpupdraw = 0;
  29.  
  30. long setcolor(long c)
  31. {
  32.     if (c == INVISIBLE) {
  33.         if (showinvisible)
  34.         color(8);
  35.     else
  36.         return 0;
  37.     } else
  38.         color((unsigned short)c);
  39.     if (c == SMEAR) {
  40.     drawmode(PUPDRAW);
  41.     inpupdraw = 1;
  42.     color(1);
  43.     }
  44.     if (c == BLINK) {
  45.     color(255);
  46.     }
  47.     return 1;
  48. }
  49.  
  50. void resetcolor()
  51. {
  52.     if (inpupdraw) {
  53.         drawmode(NORMALDRAW);
  54.     inpupdraw = 0;
  55.     }
  56. }
  57.  
  58. void comment::draw()
  59. {
  60. }
  61.  
  62. void text::draw()
  63. {
  64.     char tstr[100];
  65.     if (str[0] && showinfo) {
  66.         if (0 == setcolor(Color)) return;
  67.     sprintf(tstr, "%s", str);
  68.     charstr(tstr);
  69.     }
  70.     resetcolor();
  71. }
  72.  
  73. void comment::PostScript(FILE *fp)
  74. {
  75. }
  76.  
  77. void length::PostScript(FILE *fp)
  78. {
  79.     char str[100];
  80.     if (name[0]) {
  81.         if (INVISIBLE == Color) return;
  82.     fprintf(fp, "(%s = %f) show\n", name, value);
  83.     }
  84. }
  85.  
  86. void length::draw()
  87. {
  88.     char str[100];
  89.     if (name[0]) {
  90.         if (0 == setcolor(Color)) return;
  91.     sprintf(str, "%s = %f", name, value);
  92.     charstr(str);
  93.     }
  94.     resetcolor();
  95. }
  96.  
  97. void vertex::draw()
  98. {
  99.     float spbsize;
  100.  
  101.     if (w == 0.0) return;
  102.     if (0 == setcolor(Color)) return;
  103.     if (this == pselected) linewidth(3);
  104.     switch (type) {
  105.     case _diamond:
  106.         move2(xw-pbsize, yw); draw2(xw, yw+pbsize);
  107.         draw2(xw+pbsize, yw); draw2(xw, yw-pbsize);
  108.         draw2(xw-pbsize, yw);
  109.         linewidth(defaultwidth);
  110.         pnt2(xw, yw);
  111.         break;
  112.     case _plus:
  113.         move2(xw-pbsize, yw); draw2(xw+pbsize, yw);
  114.         move2(xw, yw-pbsize); draw2(xw, yw+pbsize);
  115.         linewidth(defaultwidth);
  116.         pnt2(xw, yw);
  117.         break;
  118.     case _cross:    // square, really
  119.         spbsize = pbsize*.707107;
  120.         move2(xw-spbsize, yw-spbsize); draw2(xw+spbsize, yw-spbsize);
  121.         draw2(xw+spbsize, yw+spbsize); draw2(xw-spbsize, yw+spbsize);
  122.         draw2(xw-spbsize, yw-spbsize);
  123.         linewidth(defaultwidth);
  124.         pnt2(xw, yw);
  125.         break;
  126.     case _nomark:
  127.         break;
  128.     case _soliddiamond:
  129.         pmv2(xw-pbsize, yw); pdr2(xw, yw+pbsize);
  130.         pdr2(xw+pbsize, yw); pdr2(xw, yw-pbsize);
  131.         pdr2(xw-pbsize, yw); pclos();
  132.         linewidth(defaultwidth);
  133.         break;
  134.     }
  135.     if (name[0]) {
  136.     cmov2(xw + pbsize/2, yw + pbsize/2);
  137.     charstr(name);
  138.     }
  139.     resetcolor();
  140. }
  141.  
  142. #define VERTEXWIDTH    (0.0025)
  143. #define LINEWIDTH    (0.0040)
  144.  
  145. int infinite(float x, float y) 
  146. {
  147.     if(x<0.0)
  148.     x = -x;
  149.     if(x>2.0)
  150.     return 1;
  151.     if(y<0.0)
  152.     y = -y;
  153.     if(y>2.0)
  154.     return 1;
  155.     return 0;
  156. }
  157.  
  158. double flerp(double f0,double f1,double p)
  159. {
  160.     return ((f0*(1.0-p))+(f1*p));
  161. }
  162.  
  163. int clipedge1(double *x1, double *y1, double *x2, double *y2)
  164. {
  165.     float p;
  166.  
  167.     if(*x1<0.0 && *x2<0.0) 
  168.     return 1;
  169.     if(*x1<0.0 && *x2>0.0) {
  170.     p = -(*x1)/((*x2)-(*x1)); 
  171.     *x1 = 0.0;
  172.     *y1 = flerp(*y1,*y2,p);
  173.     } else if(*x1>0.0 && *x2<0.0) {
  174.     p = -(*x2)/((*x1)-(*x2)); 
  175.     *x2 = 0.0;
  176.     *y2 = flerp(*y2,*y1,p);
  177.     }
  178.     return 0;
  179. }
  180.  
  181. int clipedge2(double *x1, double *y1, double *x2, double *y2)
  182. {
  183.     if(clipedge1(x1,y1,x2,y2))
  184.        return 1;
  185.     *x1 = 1.0-(*x1);
  186.     *x2 = 1.0-(*x2);
  187.     if(clipedge1(x1,y1,x2,y2))
  188.        return 1;
  189.     *x1 = 1.0-(*x1);
  190.     *x2 = 1.0-(*x2);
  191.     return 0;
  192. }
  193.  
  194. int clipline(double *x1, double *y1, double *x2, double *y2)
  195. {
  196.     if(clipedge2(x1,y1,x2,y2))
  197.        return 1;
  198.     if(clipedge2(y1,x1,y2,x2))
  199.        return 1;
  200.     return 0;
  201. }
  202.  
  203. void drawline(FILE *fp, float x1, float y1, float x2, float y2)
  204. {
  205.     double fx1, fy1, fx2, fy2;
  206.  
  207.     fx1 = (x1+1.0)/2.0;
  208.     fy1 = (y1+1.0)/2.0;
  209.     fx2 = (x2+1.0)/2.0;
  210.     fy2 = (y2+1.0)/2.0;
  211.     if(clipline(&fx1,&fy1,&fx2,&fy2))
  212.     return;
  213.     x1 = (2.0*fx1)-1.0;
  214.     y1 = (2.0*fy1)-1.0;
  215.     x2 = (2.0*fx2)-1.0;
  216.     y2 = (2.0*fy2)-1.0;
  217.     fprintf(fp, "newpath\n");
  218.     fprintf(fp, "%f %f moveto\n", x1, y1);
  219.     fprintf(fp, "%f %f lineto\n", x2, y2);
  220.     fprintf(fp, "stroke\n");
  221. }
  222.  
  223. void setlinestyle(FILE *fp, int val)
  224. {
  225.     switch(val) {
  226.     case 0:
  227.         fprintf(fp, "[0.020 0.010] 0 setdash\n");
  228.         fprintf(fp, "%f setlinewidth\n",LINEWIDTH/24.0);
  229.         break;
  230.     case 1:
  231.         fprintf(fp, "[] 0 setdash\n");
  232.         fprintf(fp, "%f setlinewidth\n",LINEWIDTH);
  233.         break;
  234.     }
  235. }
  236.  
  237. extern void setPScolor(long, FILE *);
  238.  
  239. void vertex::PostScript(FILE *fp)
  240. {
  241.     if (Color == INVISIBLE) return;
  242.     if (w == 0.0) return;
  243.     setlinestyle(fp,1);
  244.     fprintf(fp, "1 setgray\n");
  245.     fprintf(fp, "newpath\n");
  246.     fprintf(fp, "%f %f %f 0 360 arc closepath fill\n", xw, yw, pbsize/2.0);
  247.     setPScolor(Color, fp);
  248.     fprintf(fp, "%f setlinewidth\n",VERTEXWIDTH);
  249.     fprintf(fp, "newpath\n");
  250.     fprintf(fp, "%f %f %f 0 360 arc closepath stroke\n", xw, yw, pbsize/2.0);
  251.     if (name[0]) {
  252.     setlinestyle(fp,1);
  253.     fprintf(fp, "%f %f moveto\n", xw + pbsize/2, yw + pbsize/2);
  254.     fprintf(fp, "(%s) haloshow\n",name);
  255.     }
  256. }
  257.  
  258. void line::draw()
  259. {
  260.     float x1[2], x2[2];
  261.  
  262.     if (0 == setcolor(Color)) return;
  263.     if (v1.w != 0.0 && v2.w != 0.0 && type != _longline) {
  264.     x1[0] = v1.xw; x1[1] = v1.yw;
  265.     x2[0] = v2.xw; x2[1] = v2.yw;
  266.     switch (type) {
  267.         case _ray12:
  268.         x2[0] = x2[0] + 10000.0*(x2[0] - x1[0]);
  269.         x2[1] = x2[1] + 10000.0*(x2[1] - x1[1]);
  270.         break;
  271.         case _segment:
  272.         break;
  273.     }
  274.     } else {
  275.         if (XW == 0.0 && YW == 0.0) {
  276.         x1[0] = x2[0] = 1.0e30;
  277.         x1[1] = x2[1] = 1.0e30;
  278.     } else if (fabs(YW) >= fabs(XW)) {
  279.         x1[0] = -10.0; x2[0] = 10.0;
  280.         x1[1] = -(W + XW*x1[0])/YW;
  281.         x2[1] = -(W + XW*x2[0])/YW;
  282.     } else {
  283.         x1[1] = -10.0; x2[1] = 10.0;
  284.         x1[0] = -(W+YW*x1[1])/XW;
  285.         x2[0] = -(W+YW*x2[1])/XW;
  286.     }
  287.     }
  288.     if (this == pselected) linewidth(3);
  289.     bgnline();
  290.     v2f(x1);
  291.     v2f(x2);
  292.     endline();
  293.     linewidth(defaultwidth);
  294.     resetcolor();
  295. }
  296.  
  297. void line::PostScript(FILE *fp)
  298. {
  299.     float x1[2], x2[2];
  300.  
  301.     if (Color == INVISIBLE && showinvisible == 0) return;
  302.     if (v1.w != 0.0 && v2.w != 0.0 && type != _longline) {
  303.     x1[0] = v1.xw; x1[1] = v1.yw;
  304.     x2[0] = v2.xw; x2[1] = v2.yw;
  305.     switch (type) {
  306.         case _ray12:
  307.         x2[0] = x2[0] + 10000.0*(x2[0] - x1[0]);
  308.         x2[1] = x2[1] + 10000.0*(x2[1] - x1[1]);
  309.         break;
  310.         case _segment:
  311.         break;
  312.     }
  313.     } else {
  314.         if (XW == 0.0 && YW == 0.0) {
  315.         x1[0] = x2[0] = 1.0e30;
  316.         x1[1] = x2[1] = 1.0e30;
  317.     } else if (fabs(YW) >= fabs(XW)) {
  318.         x1[0] = -10.0; x2[0] = 10.0;
  319.         x1[1] = -(W + XW*x1[0])/YW;
  320.         x2[1] = -(W + XW*x2[0])/YW;
  321.     } else {
  322.         x1[1] = -10.0; x2[1] = 10.0;
  323.         x1[0] = -(W+YW*x1[1])/XW;
  324.         x2[0] = -(W+YW*x2[1])/XW;
  325.     }
  326.     }
  327.     if (Color == INVISIBLE)
  328.     setlinestyle(fp,0);
  329.     else
  330.     setlinestyle(fp,1);
  331.     drawline(fp,x1[0],x1[1],x2[0],x2[1]);
  332. }
  333.  
  334. void bezier::draw()
  335. {
  336.     float x1[2], x2[2], x3[2], x4[2], p[2], t;
  337.  
  338.     if (0 == setcolor(Color)) return;
  339.     if (v1.w != 0.0 && v2.w != 0.0 && v3.w != 0.0 && v4.w != 0.0) {
  340.     x1[0] = v1.xw; x1[1] = v1.yw;
  341.     x2[0] = v2.xw; x2[1] = v2.yw;
  342.     x3[0] = v3.xw; x3[1] = v3.yw;
  343.     x4[0] = v4.xw; x4[1] = v4.yw;
  344.     if (this == pselected) linewidth(3);
  345.     bgnline();
  346.     for (t = 0.0; t <= 1.001; t += .03125) {
  347.         float t3 = t*t*t;
  348.         float t2 = 3.0*t*t*(1.0-t);
  349.         float t1 = 3.0*t*(1.0-t)*(1.0-t);
  350.         float t0 = (1.0-t)*(1.0-t)*(1.0-t);
  351.         p[0] = t0*x1[0]+t1*x2[0]+t2*x3[0]+t3*x4[0];
  352.         p[1] = t0*x1[1]+t1*x2[1]+t2*x3[1]+t3*x4[1];
  353.         v2f(p);
  354.     }
  355.     endline();
  356.     linewidth(defaultwidth);
  357.     }
  358.     resetcolor();
  359. }
  360.  
  361. float bezier::disttobezier(float x, float y)
  362. {
  363.     float vmin = 1.0e30, vv;
  364.     float x1[2], x2[2], x3[2], x4[2], p[2], t;
  365.  
  366.     if (v1.w != 0.0 && v2.w != 0.0 && v3.w != 0.0 && v4.w != 0.0) {
  367.     x1[0] = v1.xw; x1[1] = v1.yw;
  368.     x2[0] = v2.xw; x2[1] = v2.yw;
  369.     x3[0] = v3.xw; x3[1] = v3.yw;
  370.     x4[0] = v4.xw; x4[1] = v4.yw;
  371.     for (t = 0.0; t <= 1.0001; t += .001) {
  372.         float t3 = t*t*t;
  373.         float t2 = 3.0*t*t*(1.0-t);
  374.         float t1 = 3.0*t*(1.0-t)*(1.0-t);
  375.         float t0 = (1.0-t)*(1.0-t)*(1.0-t);
  376.         p[0] = t0*x1[0]+t1*x2[0]+t2*x3[0]+t3*x4[0];
  377.         p[1] = t0*x1[1]+t1*x2[1]+t2*x3[1]+t3*x4[1];
  378.         vv = (p[0]-x)*(p[0]-x) + (p[1]-y)*(p[1]-y);
  379.         if (vv < vmin) vmin = vv;
  380.     }
  381.     }
  382.     return sqrt(vmin);
  383. }
  384.  
  385. void bezier::PostScript(FILE *fp)
  386. {
  387.     if (Color == INVISIBLE && showinvisible == 0) return;
  388.     if (v1.w == 0.0 || v2.w == 0.0 || v3.w == 0.0 || v4.w == 0.0) return;
  389.     if (Color == INVISIBLE)
  390.     setlinestyle(fp,0);
  391.     else
  392.     setlinestyle(fp,1);
  393.     fprintf(fp, "newpath\n");
  394.     fprintf(fp, "%f %f moveto\n", v1.xw, v1.yw);
  395.     fprintf(fp, "%f %f %f %f %f %f curveto\n",
  396.         v2.xw, v2.yw, v3.xw, v3.yw, v4.xw, v4.yw);
  397.     fprintf(fp, "stroke\n");
  398. }
  399.  
  400. static float *hypc = 0;
  401.  
  402. void hyp()
  403. {
  404.     if (hypc == 0) {
  405.         hypc = new float[1600];
  406.         hypc[0] =  -1000000.0; hypc[1] = 1000000.0;
  407.         hypc[399*2] =  1000000.0; hypc[399*2+1] = 1000000.0;
  408.         hypc[400*2] =  -1000000.0; hypc[400*2+1] = -1000000.0;
  409.         hypc[799*2] =  1000000.0; hypc[799*2+1] = -1000000.0;
  410.     for (long i = 1; i < 399; i++) {
  411.         hypc[i*2] = hypc[(i+400)*2] = -5.0 + 10.0*(i-1)/398.0;
  412.         hypc[i*2+1] = sqrt(1 + hypc[i*2]*hypc[i*2]);
  413.         hypc[(i+400)*2+1] = -hypc[i*2+1];
  414.     }
  415.     }
  416.     bgnline();
  417.     for (long i = 0; i < 400; i++) v2f(&hypc[i*2]);
  418.     endline();
  419.     bgnline();
  420.     for (i = 0; i < 400; i++) v2f(&hypc[(i+400)*2]);
  421.     endline();
  422. }
  423.  
  424. static float *circdata = 0;
  425.  
  426. void cir()
  427. {
  428.     if (circdata == 0) {
  429.         circdata = new float[1600];
  430.     for (long i = 0; i < 800; i++) {
  431.         circdata[2*i] = cos(2.0*PI*i/800);
  432.         circdata[2*i+1] = sin(2.0*PI*i/800);
  433.     }
  434.     }
  435.     bgnclosedline();
  436.     for (long i = 0; i < 800; i++) v2f(&circdata[2*i]);
  437.     endclosedline();
  438. }
  439.  
  440. // The following somewhat bizarre code is for drawing large circles.
  441. // For moderately large radii, a more accurate circle (500 points)
  442. // is drawn.  For huge circles, the part of the circle intersecting
  443. // the viewed region is drawn as two straight lines.  The lines are
  444. // preferentially drawn in the shorter direction, but if the
  445. // equations in that direction cannot be solved, the lines are drawn
  446. // in the longer direction (if possible).
  447.  
  448. void accuratecircle(float x, float y, float radius)
  449. {
  450.     float v1, v2, w1, w2;
  451.     long flipped = 0;
  452.  
  453.     if (radius > 200) {
  454.     if (fxmax - fxmin > fymax - fymin) {
  455. l1:
  456.         float d = radius*radius - (fymax-y)*(fymax-y);
  457.         if (d < 0) {
  458.         if (flipped) return;
  459.         flipped = 1;
  460.         goto l2;
  461.         }
  462.         d = sqrt(d);
  463.         v1 = x + d; v2 = x - d;
  464.         d = radius*radius - (fymin-y)*(fymin-y);
  465.         if (d < 0) {
  466.         if (flipped) return;
  467.         flipped = 1;
  468.         goto l2;
  469.         }
  470.         d = sqrt(d);
  471.         w1 = x + d; w2 = x - d;
  472.         move2(v1, fymax); draw2(w1, fymin);
  473.         move2(v2, fymax); draw2(w2, fymin);
  474.     } else {
  475. l2:
  476.         float d = radius*radius - (fxmax-x)*(fxmax-x);
  477.         if (d < 0) {
  478.         if (flipped) return;
  479.         flipped = 1;
  480.         goto l1;
  481.         }
  482.         d = sqrt(d);
  483.         v1 = y + d; v2 = y - d;
  484.         d = radius*radius - (fxmin-x)*(fxmin-x);
  485.         if (d < 0) {
  486.         if (flipped) return;
  487.         flipped = 1;
  488.         goto l1;
  489.         }
  490.         d = sqrt(d);
  491.         w1 = y + d; w2 = y - d;
  492.         move2(fxmax, v1); draw2(fxmin, w1);
  493.         move2(fxmax, v2); draw2(fxmin, w2);
  494.     }
  495.     return;
  496.     }
  497.     pushmatrix();
  498.     translate(x, y, 0.0);
  499.     scale(radius, radius, radius);
  500.     cir();
  501.     popmatrix();
  502. }
  503.  
  504. void drawaline(vertex *v1, vertex *v2, long selected)
  505. {
  506.     float XW, YW, W, x1[2], x2[2];
  507.     
  508.     XW = v1->yw*v2->w - v2->yw*v1->w;
  509.     YW = v1->w*v2->xw - v2->w*v1->xw;
  510.     W = v1->xw*v2->yw - v1->yw*v2->xw;
  511.     if (fabs(YW) >= fabs(XW)) {
  512.         x1[0] = -10.0; x2[0] = 10.0;
  513.         x1[1] = -(W + XW*x1[0])/YW;
  514.         x2[1] = -(W + XW*x2[0])/YW;
  515.     } else {
  516.         x1[1] = -10.0; x2[1] = 10.0;
  517.         x1[0] = -(W+YW*x1[1])/XW;
  518.         x2[0] = -(W+YW*x2[1])/XW;
  519.     }
  520.     if (selected) linewidth(3);
  521.     bgnline();
  522.     v2f(x1);
  523.     v2f(x2);
  524.     endline();
  525.     linewidth(defaultwidth);
  526. }
  527.  
  528. void circle::draw()
  529. {
  530.     if (0 == setcolor(Color)) return;
  531.     if (center.w != 0.0) {
  532.     float x = center.xw;
  533.     float y = center.yw;
  534.     if (this == pselected) linewidth(3);
  535.     if (radius < 4.0)
  536.         circ(x, y, radius);
  537.     else
  538.         accuratecircle(x, y, radius);
  539.     linewidth(defaultwidth);
  540.     } else {
  541.         long valid1 = (v1.w != 0.0) ? 1 : 0;
  542.     long valid2 = (v2.w != 0.0) ? 2 : 0;
  543.     long valid3 = (v3.w != 0.0) ? 4 : 0;
  544.         switch (valid1+valid2+valid3) {
  545.         case 0:
  546.             break;
  547.         case 1: case 3: case 6: case 7:
  548.             drawaline(&v1, &v2, this==pselected);
  549.         break;
  550.         case 2:
  551.             drawaline(&v2, &v1, this==pselected);
  552.         break;
  553.         case 4:
  554.             drawaline(&v3, &v1, this==pselected);
  555.         break;
  556.         case 5:
  557.             drawaline(&v1, &v3, this==pselected);
  558.         break;
  559.     }
  560.     }
  561.     resetcolor();
  562. }
  563.  
  564. void circle::PostScript(FILE *fp)
  565. {
  566.     if (Color == INVISIBLE && showinvisible == 0) return;
  567.     if (center.w != 0.0) {
  568.     float x = center.xw;
  569.     float y = center.yw;
  570.  
  571.     if (Color == INVISIBLE)
  572.         setlinestyle(fp,0);
  573.     else
  574.         setlinestyle(fp,1);
  575.     fprintf(fp, "newpath\n");
  576.     fprintf(fp, "%f %f %f 0 360 arc closepath stroke\n", x, y, radius);
  577.     }
  578. }
  579.  
  580. long vertex::hitvertex(float x, float y)
  581. {
  582.     if (showinvisible == 0 && Color == INVISIBLE) return 0;
  583.     if (w == 0.0) return 0;
  584.     if (x < xw - TOL) return 0;
  585.     if (x > xw + TOL) return 0;
  586.     if (y < yw - TOL) return 0;
  587.     if (y > yw + TOL) return 0;
  588.     return 1;
  589. }
  590.  
  591. long line::hitline(float x, float y)
  592. {
  593.     if (showinvisible == 0 && Color == INVISIBLE) return 0;
  594.     if (disttoline(x, y) < TOL/2.0) return 1;
  595.     return 0;
  596. }
  597.  
  598. long conic::hitconic(float x, float y)
  599. {
  600.     if (showinvisible == 0 && Color == INVISIBLE) return 0;
  601.     if (disttoconic(x, y) < TOL) return 1;
  602.     return 0;
  603. }
  604.  
  605. long bezier::hitbezier(float x, float y)
  606. {
  607.     if (showinvisible == 0 && Color == INVISIBLE) return 0;
  608.     if (disttobezier(x, y) < TOL/2.0) return 1;
  609.     return 0;
  610. }
  611.  
  612. long circle::hitcircle(float x, float y)
  613. {
  614.     if (showinvisible == 0 && Color == INVISIBLE) return 0;
  615.     if (disttocircle(x, y) < TOL/2.0) return 1;
  616.     return 0;
  617. }
  618.  
  619. void vertonlineline(vertex *, line *, line *);
  620.  
  621. void vertex::projecttoline(line *l)
  622. {
  623.     line ll;
  624.     ll.XW = -l->YW; ll.YW = l->XW;
  625.     ll.W = -(xw*ll.XW + yw*ll.YW);
  626.     vertonlineline(this, l, &ll);
  627. }
  628.  
  629. float line::disttoline(float x, float y)
  630. {
  631.     if (XW == 0.0 && YW == 0.0) return 1.0e30;
  632.     float d = (XW*x + YW*y + W)/sqrt(XW*XW+YW*YW);
  633.     return fabs(d);
  634. }
  635.  
  636. float circle::disttocircle(float x, float y)    // needs work XXX
  637. {
  638.     float x0 = center.xw/center.w;
  639.     float y0 = center.yw/center.w;
  640.     float R = sqrt((x0-x)*(x0-x)+(y0-y)*(y0-y));
  641.     R = R-radius;
  642.     return (R >= 0.0) ? R : -R;
  643. }
  644.  
  645. float conic::disttoconic(float x, float y)
  646. {
  647.     float dist = 1.0e30, dt;
  648.     float xval, yval, u;
  649.     
  650.     for (xval = fxmin; xval <= fxmax; xval += .01) {
  651.     float a = cc;
  652.     float b = bb*xval + ee;
  653.     float c = aa*xval*xval + dd*xval + ff;
  654.     if ((u = b*b - 4.0*a*c) >= 0) {
  655.         float disc = sqrt(b*b - 4.0*a*c);
  656.         float y1 = (-b + disc)/(2*a);
  657.         float y2 = (-b - disc)/(2*a);
  658.         if ((dt=(x-xval)*(x-xval)+(y1-y)*(y1-y))<dist) dist = dt;
  659.         if ((dt=(x-xval)*(x-xval)+(y2-y)*(y2-y))<dist) dist = dt;
  660.     }
  661.     }
  662.     for (yval = fymin; yval <= fymax; yval += .01) {
  663.     float a = aa;
  664.     float b = bb*yval + dd;
  665.     float c = cc*yval*yval + ee*yval + ff;
  666.     if ((u = b*b - 4.0*a*c) >= 0) {
  667.         float disc = sqrt(b*b - 4.0*a*c);
  668.         float x1 = (-b + disc)/(2*a);
  669.         float x2 = (-b - disc)/(2*a);
  670.         if ((dt=(x-x1)*(x-x1)+(y-yval)*(y-yval))<dist) dist = dt;
  671.         if ((dt=(x-x2)*(x-x2)+(y-yval)*(y-yval))<dist) dist = dt;
  672.     }
  673.     }
  674.     return sqrt(dist);
  675. }
  676.  
  677. void conic::draw()
  678. {
  679.     double theta = atan2(bb, aa-cc)/2.0;
  680.     double Cos = cos(theta), Sin = sin(theta);
  681.     double AA = aa*Cos*Cos + bb*Cos*Sin + cc*Sin*Sin;
  682.     double CC = aa*Sin*Sin - bb*Cos*Sin + cc*Cos*Cos;
  683.     double DD = dd*Cos + ee*Sin;
  684.     double EE = ee*Cos - dd*Sin;
  685.     double FF = ff;
  686.     if (fabs(AA) < 5.0e-3 || fabs(CC) < 5.0e-3) { // it's a parabola
  687.         float y, dy, x, dx, pt[2];
  688.     if (0 == setcolor(Color)) return;
  689.     if (this == pselected) linewidth(3);
  690.     pushmatrix();
  691.     rot(theta*180.0/PI, 'z');
  692.     bgnline();
  693.     if (fabs(AA) < 5.0e-3) {
  694.         dy = 2*(fymax - fymin) / 80;
  695.         for (y = fymin-20*dy; y < fymax+20*dy; y += dy) {
  696.         x = -(CC*y*y+EE*y+FF)/DD;
  697.         pt[0] = x;
  698.         pt[1] = y;
  699.         v2f(pt);
  700.         }
  701.     } else {
  702.         dx = 2*(fxmax - fxmin) / 80;
  703.         for (x = fxmin-20*dx; x < fxmax+20*dx; x += dx) {
  704.         y = -(AA*x*x+DD*x+FF)/EE;
  705.         pt[0] = x;
  706.         pt[1] = y;
  707.         v2f(pt);
  708.         }
  709.     }
  710.     endline();
  711.     popmatrix();
  712.     linewidth(defaultwidth);
  713.     resetcolor();
  714.     return;
  715.     }
  716.     float transx = -DD/(2.0*AA), transy = -EE/(2.0*CC);
  717.     FF = FF + AA*transx*transx + CC*transy*transy + DD*transx + EE*transy;
  718.     AA = AA/FF; CC = CC/FF;
  719.     // equation is now: AA*x*x + CC*y*y + 1 = 0;
  720.     if (AA > 0.0 && CC > 0.0) return;
  721.     if (0 == setcolor(Color)) return;
  722.     if (this == pselected) linewidth(3);
  723.     if (AA < 0.0 && CC < 0.0) {
  724.         float scalex = 1.0/sqrt(-AA), scaley = 1.0/sqrt(-CC);
  725.     pushmatrix();
  726.     rot(theta*180.0/PI, 'z');
  727.     translate(transx, transy, 0.0);
  728.     scale(scalex, scaley, 1.0);
  729.     cir();
  730.     popmatrix();
  731.     } else {
  732.         float scalex, scaley;
  733.     if (AA > 0.0) scalex = 1.0/sqrt(AA); else scalex = 1.0/sqrt(-AA);
  734.     if (CC > 0.0) scaley = 1.0/sqrt(CC); else scaley = 1.0/sqrt(-CC);
  735.     pushmatrix();
  736.     rot(theta*180.0/PI, 'z');
  737.     translate(transx, transy, 0.0);
  738.     scale(scalex, scaley, 1.0);
  739.         if (CC > 0.0)
  740.         rot(90.0, 'z');
  741.     hyp();
  742.     popmatrix();
  743.     }
  744.     linewidth(defaultwidth);
  745.     resetcolor();
  746. }
  747.  
  748. void conic::PostScript(FILE *fp)
  749. {
  750.     if (Color == INVISIBLE && showinvisible == 0) return;
  751.     if (Color == INVISIBLE)
  752.     setlinestyle(fp,0);
  753.     else
  754.     setlinestyle(fp,1);
  755.     double theta = atan2(bb, aa-cc)/2.0;
  756.     double Cos = cos(theta), Sin = sin(theta);
  757.     float AA = aa*Cos*Cos + bb*Cos*Sin + cc*Sin*Sin;
  758.     float CC = aa*Sin*Sin - bb*Cos*Sin + cc*Cos*Cos;
  759.     float DD = dd*Cos + ee*Sin;
  760.     float EE = ee*Cos - dd*Sin;
  761.     float FF = ff;
  762.     float transx = -DD/(2.0*AA), transy = -EE/(2.0*CC);
  763.     FF = FF + AA*transx*transx + CC*transy*transy + DD*transx + EE*transy;
  764.     AA = AA/FF; CC = CC/FF;
  765.     // equation is now: AA*x*x + CC*y*y + 1 = 0;
  766.     if (AA > 0.0 && CC > 0.0) return;
  767.     if (0 == setcolor(Color)) return;
  768.     if (this == pselected) linewidth(3);
  769.     if (AA < 0.0 && CC < 0.0) {
  770.         float scalex = 1.0/sqrt(-AA), scaley = 1.0/sqrt(-CC);
  771.     fprintf(fp, "gsave\n");
  772.     fprintf(fp, "%g rotate\n", theta*180/PI);
  773.     fprintf(fp, "%g %g translate\n", transx, transy);
  774.     fprintf(fp, "%g %g scale\n", scalex, scaley);
  775.     fprintf(fp, "newpath\n");
  776.     fprintf(fp, "0 0 1 0 360 arc closepath stroke\n");
  777.     fprintf(fp, "grestore\n");
  778.     } else {
  779.         float scalex, scaley;
  780.     if (AA > 0.0) scalex = 1.0/sqrt(AA); else scalex = 1.0/sqrt(-AA);
  781.     if (CC > 0.0) scaley = 1.0/sqrt(CC); else scaley = 1.0/sqrt(-CC);
  782.     fprintf(fp, "gsave\n");
  783.     fprintf(fp, "%g rotate\n", theta*180/PI);
  784.     fprintf(fp, "%g %g translate\n", transx, transy);
  785.     fprintf(fp, "%g %g scale\n", scalex, scaley);
  786.         if (CC > 0.0)
  787.         fprintf(fp, "90 rotate\n");
  788.     fprintf(fp, "newpath\n");
  789.     fprintf(fp, "%g %g moveto\n", hypc[0], hypc[1]);
  790.     for (long i = 1; i < 400; i++)
  791.         fprintf(fp, "%g %g lineto\n", hypc[i*2], hypc[i*2+1]);
  792.     fprintf(fp, "closepath stroke newpath\n");
  793.     fprintf(fp, "%g %g moveto\n", hypc[400*2], hypc[400*2+1]);
  794.     for (i = 1; i < 400; i++)
  795.         fprintf(fp, "%g %g lineto\n", hypc[(i+400)*2], hypc[(i+400)*2+1]);
  796.     fprintf(fp, "closepath stroke\n");
  797.     fprintf(fp, "grestore\n");
  798.     }
  799.     linewidth(defaultwidth);
  800.     resetcolor();
  801. }
  802.